package com.hzgj.soa.protocol.pb.serialization;

import com.baidu.bjf.remoting.protobuf.Codec;
import com.baidu.bjf.remoting.protobuf.ProtobufProxy;
import com.hzgj.bcl.soa.interceptor.Serialization;
import com.hzgj.bcl.soa.rpc.message.Message;
import com.hzgj.bcl.soa.util.Constants;
import com.hzgj.soa.protocol.pb.data.RequestMessage;
import com.hzgj.soa.protocol.pb.data.ResponseMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

import static com.hzgj.soa.protocol.pb.handler.PbConstants.PB_PROTOCOL;

/**
 * Created by warning on 2016/11/8.
 */
public class ProtobufSerialization implements Serialization {

    private Logger logger = LoggerFactory.getLogger(getClass());
    private static Codec<RequestMessage> requestCodec = ProtobufProxy.create(RequestMessage.class);
    private static Codec<ResponseMessage> responseCodec = ProtobufProxy.create(ResponseMessage.class);

    @Override
    public String getName() {
        return PB_PROTOCOL;
    }

    @Override
    public byte getId() {
        return 23;
    }

    @Override
    public byte[] write(Message message) throws Exception {
        Integer type = (Integer) message.getHeader(Constants.MESSAGE_TYPE);
        boolean request = (type == null || type == Message.REQ);
        try {
            if (request) {
                RequestMessage requestMessage = (RequestMessage) message.getPayload();
                requestMessage.messageId = (Long) message.getHeader(Constants.MESSAGE_SID);
                return requestCodec.encode(requestMessage);
            } else {
                ResponseMessage responseMessage = (ResponseMessage) message.getPayload();
                message.putHeader(Constants.MESSAGE_SID, responseMessage.messageId);
                return responseCodec.encode(responseMessage);
            }

        } catch (Exception e) {
            logger.error("{}", e);
            throw e;
        }
    }

    @Override
    public Object read(Message message) {
        Integer type = (Integer) message.getHeader(Constants.MESSAGE_TYPE);
        boolean request = (type == null || type == Message.REQ);
        try {
            if (!request) {
                ResponseMessage responseMessage = responseCodec.decode((byte[]) message.getPayload());
                message.putHeader(Constants.MESSAGE_SID, responseMessage.messageId);
                if (!responseMessage.success) {
                    message.putHeader(Constants.MESSAGE_TYPE, Message.EXC_RSP);
                }
                return responseMessage;
            } else {
                //request has deserialization to RequestMessage
                return message.getPayload();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
